import { Ref, SetupContext, computed, nextTick, ref } from "vue";
import { PopoverProps } from "../popover.props";
import { UsePopup, UsePosition } from "./types";

export function usePopup(
    props: PopoverProps,
    context: SetupContext,
    arrowRef: Ref<any>,
    popoverRef: Ref<any>,
    reference: Ref<any>,
    shouldFitWidthToReference: Ref<boolean>,
    usePositionComposition: UsePosition
): UsePopup {
    const showPopover = ref(props.visible);
    const shown = computed(() => showPopover.value);

    const { fitToReference, locateToReference } = usePositionComposition;

    let hidePopverOnClickBodyHandler: ($event: MouseEvent) => any;

    function hide() {
        showPopover.value = false;
        document.body.removeEventListener('click', hidePopverOnClickBodyHandler);
        context.emit('hidden');
    }

    hidePopverOnClickBodyHandler = ($event: MouseEvent) => {
        if (!reference.value.contains($event.target as Node)) {
            const closestPopover = reference.value.closest('.popover') as HTMLElement;
            if (closestPopover) {
                closestPopover.removeEventListener('click', hidePopverOnClickBodyHandler);
            }
            hide();
        }
    };

    async function show(referenceElement: HTMLElement) {
        if (popoverRef.value && arrowRef.value && referenceElement) {
            showPopover.value = true;
            reference.value = referenceElement;
            await nextTick();
            locateToReference(referenceElement);
            if (shouldFitWidthToReference.value) {
                fitToReference(referenceElement);
            }
            document.body.addEventListener('click', hidePopverOnClickBodyHandler);
            const closestPopover = referenceElement.closest('.popover') as HTMLElement;
            if (closestPopover) {
                closestPopover.addEventListener('click', hidePopverOnClickBodyHandler);
            }
            context.emit('shown');
        }
    }

    context.expose({ hide, show, shown });

    return { showPopover, hidePopverOnClickBodyHandler };
}
